Plotter
Volume Number: 4
Issue Number: 2
Column Tag: Pascal Procedures
MultiFinder Friendly MacDraw Plotter 
By Dave Kelly, MacTutor Editorial Board & David Smith, Editor &
For the past few months, MacTutor has been running a series of editorials on the
importance of developers getting with the new way of doing things. In the last six
months, Apple has introduced a number of product enhancements that directly affect
commercial software development. These include:
• MultiFinder Quasi-Multitasking Finder
• AppleShare File Server
• New Menu Manager with nested menus
• New Color PICT format
• New Color Quickdraw Capability
• New Style-enhanced Text Edit & Clipboard type
• Multiple screen capability
• Universal Hyper-Text type data base
• Faster number crunching with 68881 chip
• New ROM interface files, MPW 2.0
• Lots of new Technical notes fixing old bugs
• New compatibility headaches
As usually happens when new goodies come on the market, everyone looks at their
old software and says “how come my version of MS____ doesn’t support this?” As
programmers and developers, we have a responsibility to bring our software up to
speed as quickly as possible with the new way of doing things. For example, the
time-consuming dialog box to change text font and style is no longer good enough when
nested menus can do the same job so much faster. Black and white windows, menus and
documents get old after using color for a few weeks. Big screen monitors make old style
paint programs frustrating when you can’t grow the window, or have to turn off color
to keep the program from crashing. And program development environments that once
were speedy now send the Mac into the bit-bucket because the developer can’t figure
out how to handle the switching context with a color video card installed. Even lowly
debuggers have problems trying to cope with all the system enhancements. So while
Apple has indeed given us lots of new toys, they have also given us lots of new headaches
trying to understand and upgrade our products to work with everything. If you thought
it was hard to program the Mac two years ago, pity the programmer just getting
started today. And the fact that Apple has just now managed to cleaned up the
documentation in Inside Macintosh Volume 5, doesn’t help much.
Fig. 1 Plotter Program generates hairline plots
Put Up or Shut Up
After hi-lighting commercial products which have made the transition to the new
rules of the game, we have decided to put our money where our editorial mouth is, and
attempt to publish a program that illustrates how to incorporate many of the new
system features Apple has introduced in the last six months.
Problem Solving
Since one of the hottest markets for Macintosh now is in engineering
environments, we will discuss a typical engineering approach to computer use. In
aerospace and the defense industry, the name of the game is problem solving. You use
the computer to solve a problem. It may be physics, engineering or math, but the
computer is the tool for investigating the problem and finding a solution. Let’s suppose
our problem is to build a space shuttle that flies rather than blows up. And let’s
suppose a key part of the problem is the equation for modeling the burn rate of the
solid rocket fuel in the boosters. To make things simple, we will assume the modeling
equation is quadratic in form. We want to use the computer to model this quadratic
equation and all others like it so we can determine the best model for the rocket’s
design. The problem most engineers have when trying to use the Macintosh for problem
solving, is they spend so much time figuring out how the Mac works, they never get
around to the problem! So here is a shell program for modeling and simulation
programs that follows the new Macintosh way of doing things. Our “Plotter” program
analyzes the quadratic equation and plots it with the following Mac features:
• Dialog box for user-friendly input of parameters
• Equation plotted as a Quickdraw picture
• Plot can be saved to disk as a PICT file
• Program supports printing:
• hairline line width for graph
• Choice of window size or paper size
• Plot Window is growable, zoomable, moveable
• Plot can be opened and edited in MacDraw
• Plot can be placed in Pagemaker
• Uses Quickdraw and Postscript comments
• Supports WaitNextEvent for MultiFinder use
• Quickdraw colors for menus, graph, axis
• Nested menus allow color changes
Mac Modeling Requires Quickdraw
One of the big problems in trying to model equations on the Macintosh is how to
create a Quickdraw Picture. Naturally you could just draw it on the screen as a
paint-type bit-map, but then you couldn’t take advantage of the higher resolution of
the LaserWriter to show the details of the plot. Once a plot is created, you want to be
able to save and edit it to add notes, or even move the graph around the axis. To do this,
the parts of the plot have to be created as MacDraw type objects. Yet they also have to
be grouped or else you end up with 200 date points being re-positioned on the page by
a careless mouse. When the plot is finished you have to be able to print or import it
into a program like Pagemaker to show it to someone. So how to you create a program
that does all this?
Check Your Library!
First, you make sure your supply to Technical Notes is up to date. Many of these
features are documented and supported by the just released Volume Five of Inside
Macintosh, and by a rash of new Technical Notes released since the last Boston Expo.
Here are some of the notes that deal with the problems of pictures from the point of
view of modeling equations.
• 21 Internal Picture format 11/86
• 27 MacDraw Picture Format 9/86
• 59 Pictures and Clip Regions 1/86
• 72 Optimizing for the Laser 3/86
• 91 Picture Comments 3/87
• 152 Using Laser Prep routines 7/87
• 154 Displaying large PICT files 7/87
• 155 Handles & Pointers 9/87
• 181 Picture Comments 11/87
• 183 Position Independent PS 11/87
In addition, there is the LaserWriter Technical manual, a new PICT File Format
Notes, and Mac Example Applications, ver. 1.0. These three publications, available
from APDA, include a wealth of information on how to create and print Quickdraw
pictures and pic comments, both MacDraw and Postscript comments.
The problem of making an application MultiFinder friendly is partly addressed in
the following technical notes as well as the recently released MultiFinder Development
Package, ver. 1.0, from APDA:
• 158 Asked MultiFinder Questions 9/87
• 177 Sleep Parameter problem 11/87
• 180 MultiFinder Miscellanea 11/87
One of the best “overview” publications of how to implement all of the new
goodies, e specially color, is Dave Wilson’s new note collection, Programming the
Macintosh II. This is available from MacTutor’s mail order store, in this issue. Dave
has collected the slides from his Mac II seminar at last year’s Boston Expo and
published his color paint program source code to provide a nice one-stop shopping
center for all of the features in our program this month. Finally, you should plan on
getting the Professional Programmer’s Extender from Invention Software. This
contains all of the source code for volumes 1 and 2 of their extender products. This is
also available from the MacTutor mail order store, in this issue. It is much faster to
cut and paste source code from someone else, then re-invent the wheel yourself.
For those who like books (and have the time to read them), your in luck, if you
use Borland’s Turbo Pascal for the Mac. A rash of new books have been released
including Macintosh Turbo Pascal by Tom Swan [Wiley & Sons] and Turbo Pascal for
the Mac by Leon Wortman [Tab Books]. Borland has also released a bunch of goodies
including Turbo Pascal Tutor, and Numerical Methods Toolbox. I make it a habit to just
visit my local computer bookstore regularly and buy anything with Mac on it. Call it a
business expense!
How to Use the New Goodies
Our program this month features the full Macintosh User Interface, as
documented in the recently released Human Interface Guidelines: The Apple Desktop
Interface, published Addison-Wesley, for Apple. It would be a great challenge to take
this book as a program definition and attempt to write a demo program that included
full support for every feature in this book, showing how the full User Interface is
implemented. The main program, and a unit called MyPlotStuff, implement the
standard event loop for a single window application. Much of this was cut from the
Multi-Window Text Editor MacTutor published last year. As I said, its always faster to
cut and paste than re-invent. To support color, a color array is set up in the InitMac
routine to define the eight Quickdraw colors. This way the program can run on all Macs
without a lot of special programming. (Apple really needs to put color quickdraw into
the SE so that all machines have the same version of Quickdraw, even if they can’t show
color.)
MultiFinder Friendly
To be considered MultiFinder friendly, an application has to call WaitNextEvent
and support suspend and resume events correctly. Our program works under
MultiFinder and is e specially useful with MacDraw, saving and opening our graphs
between the two programs. But it wasn’t easy figuring out how to do it. The first
problem we had was that neither Think’s Lightspeed Pascal nor Borland’s Turbo Pascal
support the final MPW 2.0 interfaces. The latest versions, (LS Pascal 1.11 and Turbo
Pascal 1.1) both use MPW 2.0 beta interfaces and so do not include either the
SysEnvirons glue, nor the WaitNextEvent interface. To get around this, I added the
WaitNextEvent definition to the ROM85 library for LS Pascal. Since SysEnvirons is an
OS trap, I suspect you can’t call it without assembly glue to manage the register set-up
so it is commented out in the listing. I just assumed the Mac was a Plus, SE or II with
the latest system.
Where is WaitNextEvent
The MultiFinder documentation says you should call WaitNextEvent if it is
present. Otherwise, call GetNextEvent and SystemTask. So you have to check the
unimplemented trap call to find out and set a flag so you will know which event trap to
use. I did this and after a while I noticed the program always said the WaitNextEvent
trap was unimplemented. What? I have a Mac II with the latest system. How can it be
unimplemented? Where is it? I called several people, both at Borland and Think, but
no one knew the answer. Finally, after studying two sample programs from the
MultiFinder Developer’s package previously mentioned, I noticed their programs
didn’t seem to have any problem. It finally dawned on me. WaitNextEvent is inside
MultiFinder! Thus it only exists when your application is running under MultiFinder,
when I suppose it gets patched into the system. Under the Finder, it’s not there so you
have to check for it. You would think this little gem would have been included in the
documentation somewhere. Alas, I don’t have either the final Volume 5 of IM, nor the
final MultiFinder Developer’s package!
Our plot is stored as a picture in a data structure called PlotDocHandle. We set up
the document in our InitMyWindow routine in the normal manner. Note that all the
rectangles we will need are set here, relative to the window’s portRect. We also do a
ClipRect to set the clipping region of the window’s grafport so we don’t have any
Quickdraw problems a la tech note 59.
Fig. 2 Our menus include a nested color menu
Our InitMyMenus routine includes an apple, file and edit menu as well as a nested
menu for color and a menu for some printing options. The data structures are designed
to make it easy to check the nested menu items and this code depends heavily on both
Dave Wilson’s programming examples, and other code segments I’ve seen.
The Mighty Update Event
Our doMouse, Keydowns, and activate routines are pretty standard user interface
stuff so no need to go over those here. The Update routine, is critical. The ideal for all
Macintosh programs is to never draw anything! The application creates a Quickdraw
picture or pictures and then invalidates some portion of the screen, causing an update
event. Then, in the Update Event routine, you call DrawPicture to display the results of
all the other application code that has been maintaining and modifying those pictures. It
has always been a mystery to me how you create the perfect Update Event routine. Here
is how ours works:
• Save and set the current grafport
• Begin Update to restrict the visRgn to the collection of invalid rgns that need
updating.
• Erase the window’s portRect.
• Set the clip rgn to the window’s portRect.
• Draw the picture.
• Draw the grow icon.
• End the update, restoring the VisRgn.
Exactly why all of these steps are needed, in that order is a mystery to me, but it
works. The window’s portRect encloses the content region of the window, which
includes everything but the title bar. In particular, it includes the scroller and grow
icon regions. So when you erase that, you have to re-draw the grow icon. The picture is
drawn in what I call the PicRect, or the application area of the content region, not
including the scroller areas. When a grow window event takes place, these rectangles
have to be carefully updated so that the next update event will work properly.
MultiFinder Support
Our doMulti routine implements the suspend and resume events from
MultiFinder. Basically, it is a carbon copy of our activate / deactivate event routine.
Since it is not really an event, we have to do a lot of processing to check for suspend or
resume, and for a mouse moved event, if we are supporting that feature of MultiFinder.
Our program is set up for it, but we don’t support it, since, for multiple monitors,
you have to do a lot of region arithmetic I don’t fully understand. The beta
documentation also says we have to call SystemEvent and post an activate event if a DA
is the front window when we are suspended or resumed. I have included this code in our
doMulti routine, but it may not be necessary. I’m looking forward to checking the final
documentation to see about this.
Our MyPlotStuff unit implements the remainder of the usual user interface. We
have an about box dialog that reads the ID string like the new Finder does and displays
it. We also find out how much memory we have left from whatever MultiFinder has
allocated to us by calling MaxMem. Our doMenuBar routine does the usual menu bar
processing, including checking the nested color menu items when the user selects a
new color. The menus also are displayed in the color of the selection thanks to the color
menu resources Steve Sheets taught us about in past issues of MacTutor.
Our grow routine is the most important one in this unit. Grow works with the
update event to change the window properly when it is resized. It is another Macintosh
mystery I’ve never fully understood. As I understand it, you have a pre-grow period
and a post-grow period, determined by when you call SizeWindow. I use the routine for
both a grow window event and a zoom window event. In the case of a zoom, you get the
new window size from the portRect, which is already set for you by the zoom. In the
case of a grow, you call GrowWindow to return the new window size. I re-calculate the
important window rectangles both before a SizeWindow and after. SizeWindow changes
the portRect of the window to the new size. So, first you invalidate the scroller, grow
and pic rectangles with the old portRect, then you SizeWindow to change the portRect,
and invalidate the scroller, grow and pic rectangles for the new window size. This
seems to correctly get all the window areas properly drawn during the update event. I
suspect we may be invalidating to many areas and that this can be re-fined so that you
only invalidate certain rectangles depending on whether the window is getting smaller
or larger. Also, if you have controls, you can move and re-size controls separately, so
they can be removed from the invalidation by calling the validate trap. If anyone has a
more efficient grow / update routine for the general case, I’d like to see it.
Fig. 3 MultiFinder support: Plotter works with MacDraw
Saving Our Graph
Once we have played around with various graphs, it would be nice to save them.
Our myFileStuff unit does the SaveAs and Save functions. To save a picture, you call the
standard file dialog and if the reply is good, you create the file, open the file, set the
file position to the start of the file and write something into the file. Then you close the
file and flush the toilet, er, volume. This is the order of calls in our doSaveAs routine,